#ifndef _NUTS_TASK_
#define _NUTS_TASK_

#include <etl/flat_multiset.h>
#include "concepts.hpp"
#include "type.hpp"

namespace nuts
{
	struct Task
	{
		using Ret_t  = i8;
		using Argv_t = void*;
		using Fn_t   = Ret_t (*)(Argv_t);
		using Pr_t   = u8;

		Fn_t fn;
		Pr_t pr     = 0;
		Argv_t argv = NULL;

		inline Ret_t
		operator()(void* args) const { return fn(args); }

		inline Ret_t
		run() { return fn(argv); }

		inline constexpr bool
		operator<(const Task& rhs) const { return this->pr < rhs.pr; }

		inline constexpr bool
		operator>(const Task& rhs) const { return this->pr > rhs.pr; }
	};

	template <u32 N>
	struct TaskList
	    : public etl::flat_multiset<Task, N>
	{
		using Base_t = etl::flat_multiset<Task, N>;

		template <Same<Task>... Tasks>
		inline void push(Tasks&&... task)
		{
			while (Base_t::full())
				;
			(..., Base_t::insert(task));
		}

		inline decltype(auto) front()
		{
			return *Base_t::begin();
		}

		inline void pop()
		{
			Base_t::erase(Base_t::begin());
		}

		inline decltype(auto) serve()
		{
			auto tmp = front();
			pop();
			return tmp;
		}

		inline void iter(auto&& fn)
		{
			for (auto& x: *this) {
				fn(x);
			}
		}
	};
}

#endif